/*
 * SyncResource.java
 *
 * Created on April 12, 2007, 1:39 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.app.admin;

import java.util.Iterator;
import java.util.UUID;
import java.util.logging.Level;
import org.atomojo.app.App;
import org.atomojo.app.InfosetRepresentation;
import org.atomojo.app.auth.AuthCredentials;
import org.atomojo.app.auth.AuthException;
import org.atomojo.app.auth.AuthService;
import org.atomojo.app.auth.User;
import org.atomojo.app.client.XMLRepresentationParser;
import org.infoset.xml.Document;
import org.infoset.xml.Element;
import org.infoset.xml.InfosetFactory;
import org.infoset.xml.ItemConstructor;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;
import org.infoset.xml.filter.RemoveDocumentFilter;
import org.infoset.xml.util.DocumentDestination;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ServerResource;

/**
 *
 * @author alex
 */
public class UsersResource extends ServerResource implements AdminXML
{
   
   XMLRepresentationParser parser = new XMLRepresentationParser();
   /** Creates a new instance of SyncResource */
   public UsersResource() {
      setNegotiated(false);
   }
   
   public Representation get()
   {
      try {
         DocumentDestination dest = new DocumentDestination();
         toXML(dest);
         InfosetRepresentation rep = new InfosetRepresentation(MediaType.APPLICATION_XML,dest.getDocument());
         rep.setCharacterSet(CharacterSet.UTF_8);
         return rep;
      } catch (XMLException ex) {
         getContext().getLogger().log(Level.SEVERE,"Cannot get users list due to XML exception: "+ex.getMessage(),ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Interal error, see logs.");
      } catch (AuthException ex) {
         getContext().getLogger().log(Level.SEVERE,"Cannot users list due authorization exception: "+ex.getMessage(),ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Interal error, see logs.");
      }
   }
   
   public void toXML(ItemDestination dest) 
      throws AuthException,XMLException
   {
      AuthService auth = (AuthService)getRequest().getAttributes().get(App.AUTH_SERVICE_ATTR);
      AuthCredentials cred = new AuthCredentials(getRequest().getChallengeResponse());
      final Iterator<User> users = auth.getUsers(cred);

      ItemConstructor constructor = InfosetFactory.getDefaultInfoset().createItemConstructor();
      dest.send(constructor.createDocument());
      dest.send(constructor.createElement(NM_USERS));
      dest.send(constructor.createCharacters("\n"));
      while (users.hasNext()) {
         User user = users.next();
         UserResource.toXML(user,new RemoveDocumentFilter(dest));
         dest.send(constructor.createCharacters("\n"));
      }
      dest.send(constructor.createElementEnd(NM_USERS));
      dest.send(constructor.createDocumentEnd());
   }
   
   public Representation post(Representation entity)
   {
      AuthService auth = (AuthService)getRequest().getAttributes().get(App.AUTH_SERVICE_ATTR);
      if (!XMLRepresentationParser.isXML(entity.getMediaType())) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Non-XML media type for entity body: "+entity.getMediaType().getName());
      }
      Document doc = null;
      try {
         doc = parser.load(entity);
      } catch (Exception ex) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("XML parse error: "+ex.getMessage());
      }
      
      Element top = doc.getDocumentElement();
      if (!top.getName().equals(NM_USER)) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Unknown document element: "+top.getName());
      }
      String alias = top.getAttributeValue("alias");
      String password = top.getAttributeValue("password");
      if (password==null) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("The password is missing.");
      }
      
      alias = alias.trim();
      password = password.trim();
      if (alias.length()==0 || password.length()==0) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Empty alias or password.");
      }
      
      Element nameE = top.getFirstElementNamed(NM_NAME);
      String name = null;
      if (nameE!=null) {
         name = nameE.getText();
      } else {
         name = alias;
      }
      Element emailE = top.getFirstElementNamed(NM_EMAIL);
      String email = null;
      if (emailE!=null) {
         email = emailE.getText();
      }
      try {
         AuthCredentials cred = new AuthCredentials(getRequest().getChallengeResponse());
         if (auth.getUser(cred,alias)!=null) {
            getResponse().setStatus(Status.CLIENT_ERROR_CONFLICT);
            return new StringRepresentation("User "+alias+" already exists.");
         } else {
            UUID id = UUID.randomUUID();
            try {
               auth.createUser(cred,alias,name,email,password);
               getResponse().setStatus(Status.SUCCESS_CREATED);
               Reference ref = new Reference(getRequest().getResourceRef().toString()+"/"+alias);
               getResponse().setLocationRef(ref);
               return null;
            } catch (AuthException ex) {
               getContext().getLogger().log(Level.SEVERE,"Cannot create user "+alias+": "+ex.getMessage(),ex);
               getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
               return new StringRepresentation("Internal error during create, see logs.");
            }
         }
      } catch (AuthException ex) {
         getContext().getLogger().log(Level.SEVERE,"Authorization error during creation of user "+alias+": "+ex.getMessage(),ex);
         getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
         return new StringRepresentation("Internal error during create, see logs.");
      }
   }
      
}
